// 获取天气信息
String getWeatherInfo() {
    String requestUrl = "https://" + String(apiUrl) + endpoint + "?location=" + locationId + "&key=" + apiKey;
    Serial.println("\n=== 开始获取天气数据 ===");
    Serial.println("请求URL: " + requestUrl);

    int retryCount = 3;
    while (retryCount > 0) {
        client.setInsecure();
        if (!client.connect(apiUrl, 443)) {
            Serial.println("❌ API连接失败");
            retryCount--;
            continue;
        }
        Serial.println("✅ 成功连接API服务器");

        String request = "GET " + String(endpoint) + "?location=" + locationId + "&key=" + apiKey + " HTTP/1.1\r\n";
        request += "Host: " + String(apiUrl) + "\r\n";
        request += "User-Agent: ESP8266 Weather Display/1.0\r\n";
        request += "Connection: close\r\n\r\n";

        client.print(request);
        Serial.println("✅ HTTP请求已发送");

        String response = "";
        // 读取并解析HTTP响应头
        bool foundContentLength = false;
        int contentLength = 0;
        
        // 读取响应头直到找到空行
        while (client.connected()) {
            String line = client.readStringUntil('\n');
            response += line;
            
            // 检查是否是Content-Length行
            if (line.startsWith("Content-Length: ")) {
                contentLength = line.substring(16).toInt();
                foundContentLength = true;
                Serial.print("✅ 找到Content-Length: ");
                Serial.println(contentLength);
            }
            
            // 空行表示响应头结束
            if (line == "\r") {
                Serial.println("✅ 响应头解析完成，开始读取响应体");
                break;
            }
        }
        
        // 读取响应体
        if (foundContentLength && contentLength > 0) {
            // 分配足够的缓冲区
            char* buffer = (char*)malloc(contentLength + 1);
            if (buffer == NULL) {
                Serial.println("❌ 内存分配失败");
                client.stop();
                retryCount--;
                continue;
            }
            
            // 读取指定长度的响应体
            int bytesRead = 0;
            unsigned long timeout = millis();
            
            while (client.connected() && bytesRead < contentLength && (millis() - timeout < 5000)) {
                if (client.available()) {
                    int bytesAvailable = client.available();
                    int bytesToRead = min(bytesAvailable, contentLength - bytesRead);
                    int bytes = client.readBytes(buffer + bytesRead, bytesToRead);
                    bytesRead += bytes;
                    timeout = millis(); // 重置超时计时器
                }
            }
            
            // 添加字符串结束符
            buffer[bytesRead] = '\0';
            
            // 将响应体添加到完整响应中
            response += String(buffer);
            free(buffer); // 释放内存
            
            Serial.print("✅ 读取响应体完成，总长度: ");
            Serial.println(response.length());
        } else {
            // 如果未找到Content-Length，按旧方法读取
            Serial.println("⚠️ 未找到Content-Length，使用旧方法读取数据");
            unsigned long timeout = millis();
            while (client.connected() && (millis() - timeout < 10000)) {
                if (client.available()) {
                    response += client.readStringUntil('\n');
                }
            }
        }
        
        client.stop();
        Serial.println("=== 接收响应数据 ===");
        Serial.println("原始响应:");
        Serial.println(response);

        int startIndex = response.indexOf("{");
        if (startIndex == -1 || response.length() - startIndex < 10) {
            // 检查JSON数据完整性，若长度过短也视为无效
            Serial.println("❌ 未找到JSON数据或数据不完整");
            retryCount--;
            continue;
        }
        response = response.substring(startIndex);

        DynamicJsonDocument doc(2048);
        DeserializationError error = deserializeJson(doc, response);
        if (error) {
            Serial.print("❌ JSON解析错误: ");
            Serial.println(error.c_str());
            retryCount--;
            continue;
        }

        if (doc["code"].as<String>() != "200") {
            Serial.print("❌ API错误码: ");
            Serial.println(doc["code"].as<String>());
            retryCount--;
            continue;
        }

        // 提取并拼接所有需要的数据
        String weatherText = doc["now"]["text"].as<String>();
        String temperature = doc["now"]["temp"].as<String>();
        String feelsLike = doc["now"]["feelsLike"].as<String>();
        String windDir = doc["now"]["windDir"].as<String>();
        String windScale = doc["now"]["windScale"].as<String>();
        String humidity = doc["now"]["humidity"].as<String>();
        String pressure = doc["now"]["pressure"].as<String>();
        String vis = doc["now"]["vis"].as<String>();
        String cloud = doc["now"]["cloud"].as<String>();
        String dew = doc["now"]["dew"].as<String>();

        String fullWeatherInfo = "天气: " + weatherText + "\n";
        fullWeatherInfo += "温度: " + temperature + "°C\n";
        fullWeatherInfo += "体感温度: " + feelsLike + "°C\n";
        fullWeatherInfo += "风向: " + windDir + "\n";
        fullWeatherInfo += "风力: " + windScale + "级\n";
        fullWeatherInfo += "湿度: " + humidity + "%\n";
        fullWeatherInfo += "气压: " + pressure + "hPa\n";
        fullWeatherInfo += "能见度: " + vis + "km\n";
        fullWeatherInfo += "云量: " + cloud + "\n";
        fullWeatherInfo += "露点: " + dew + "°C";

        Serial.println("✅ 解析成功 - 完整天气信息:");
        Serial.println(fullWeatherInfo);

        return fullWeatherInfo;
    }
    Serial.println("❌ 多次尝试后仍无法获取有效天气数据");
    return "null";
}